#include "sprite.h"
#include "debug.h"
#include <stdio.h>

static void init_spr(sprite_t* spr){
    if(!spr){return;}
    spr->loc.w = spr->loc.h = spr->loc.x = spr->loc.y = 0;
#ifdef OPENGL
    spr->tex.texture = 0;
    spr->tex.texx = spr->tex.texy = 0.0f;
    spr->tex.texx2 = spr->tex.texy2 = 1.0f;
    spr->tex.texw = spr->loc.w;
    spr->tex.texh = spr->loc.h;
#endif
}

sprite_t* crt_spr(){
    sprite_t *ret = (sprite_t*)malloc(sizeof(sprite_t));
    if(ret == NULL){
        dbg_msg("Unable to malloc new sprite\n");
        exit(1);
    }

    if(ret){
        init_spr(ret);
    }
    return ret;
}

int change_texture_location(sprite_t *spr, const int x, const int y,
        const int width, const int height){
    spr->loc.w = (short)width;
    spr->loc.h = (short)height;
#ifdef OPENGL
    spr->tex.texx = ((float)x)/(float)spr->tex.texw;
    spr->tex.texy = ((float)y)/(float)spr->tex.texh;
    //printf("%d, %d, %f\n", spr->w, width, ret->texx);
    spr->tex.texx2 = spr->tex.texx + (((float)width)/(float)spr->tex.texw);
    spr->tex.texy2 = spr->tex.texy + (((float)height)/(float)spr->tex.texh);
#endif /*OPENGL*/
    //printf("(%f, %f, %f, %f)\n", ret->texx, ret->texy, ret->texx2, ret->texy2);
    return 0;
}

sprite_t* create_sub_spr(const sprite_t *spr, const int x, const int y, 
        const int width, const int height){
    sprite_t* ret = crt_spr();

    if(!ret){return ret;}

#ifdef OPENGL
    ret->tex.texture = spr->tex.texture;
    ret->tex.texw = spr->tex.texw;
    ret->tex.texh = spr->tex.texh;
#endif /*OPENGL*/
    change_texture_location(ret, x, y, width, height);
    /*
    ret->w = (short)width;
    ret->h = (short)height;
    ret->texx = ((float)x)/(float)spr->w;
    ret->texy = ((float)y)/(float)spr->h;
    //printf("%d, %d, %f\n", spr->w, width, ret->texx);
    ret->texx2 = ret->texx + (((float)width)/(float)spr->w);
    ret->texy2 = ret->texy + (((float)height)/(float)spr->h);
    //printf("(%f, %f, %f, %f)\n", ret->texx, ret->texy, ret->texx2, ret->texy2);
    */

    return ret;
}

void free_spr(sprite_t **spr){
    //FIXME: free the texture!
    //glDeleteTextures( 1, &texture );
    free(*spr);
    *spr = NULL;
}

static void init_sprite_node(sprite_list_node_t* node){
    if(!node){return;}
    node->spr = NULL;
    node->next = node->prev = NULL;
}

sprite_list_node_t* create_sprite_list(){
    sprite_list_node_t *ret;

    ret = malloc(sizeof(sprite_list_node_t));
    if(ret){
        init_sprite_node(ret);
    }

    return ret;
}

void free_sprite_list(sprite_list_node_t **_list){
    sprite_list_node_t *list; 
    
    if(_list == NULL || *_list == NULL){return;}
    for(list = *_list; list->prev != NULL; list = list->prev){;}

    while(list->next != NULL){
        list = list->next;
        free(list->prev);
    }
    free(list);
    *_list = NULL;
}

sprite_list_node_t* sprite_list_add(sprite_list_node_t *head, sprite_t *spr){
    sprite_list_node_t *ret;

    if(head == NULL || spr == NULL){return NULL;}

    for(;head->prev; head = head->prev){;}

    if(!head->spr){
        head->spr = spr;
        return head;
    }

    for(;head->next != NULL && head->spr->loc.y > spr->loc.y; head = head->next){;}

    ret = (sprite_list_node_t*)malloc(sizeof(sprite_list_node_t));

    if(ret == NULL){
        dbg_msg("Unable to malloc node for new sprite\n");
        exit(1);
    }
    ret->spr = spr;

    if(head->spr->loc.y > spr->loc.y){
        ret->next = head->next;
        ret->prev = head;
        head->next = ret;
        if(ret->next){
            ret->next->prev = ret;
        }
    }else{
        ret->next = head;
        ret->prev = head->prev;
        if(head->prev){
            head->prev->next = ret;
        }
        head->prev = ret;
        //printf("2: %ld, %ld, %ld, %ld (%ld, %ld)\n", ret->prev, ret->next, head->prev, head->next, ret, head);
        //exit(1);
    }
    return ret;
}

/* If node is the only one, unlink the sprite and return.
 * If node->prev is NULL, free node, return node->next.
 * Otheriwse free node, return node->prev.
*/
sprite_list_node_t* sprite_list_remove(sprite_list_node_t *spr_node){
    if(spr_node == NULL){return spr_node;}

    if(spr_node->next == NULL && spr_node->prev == NULL){
        spr_node->spr = NULL;
        return spr_node;
    }

    if(spr_node->prev == NULL){
        spr_node = spr_node->next;
        free(spr_node->prev);
        spr_node->prev = NULL;
        return spr_node;
    }

    if(spr_node->next == NULL){
        spr_node = spr_node->prev;
        free(spr_node->next);
        spr_node->next = NULL;
        return spr_node;
    }

    spr_node->next->prev = spr_node->prev;
    spr_node->prev->next = spr_node->next;
    spr_node = spr_node->prev;
    free(spr_node->next);
    return spr_node;
}

